home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
mxcode
/
fmplay11
/
adlib.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-26
|
6KB
|
198 lines
/* The original version of this file was written by Kevin A. Lee */
/* (all the bugs are HIS fault. (just kidding)) */
#include <conio.h>
#include <time.h>
#include <dos.h>
#include "adlib.h"
/**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING***\
* This module MUST be compiled with stack checking OFF in BC 3.0 *
\**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING***/
/* We wish that THIS would turn stack checking off, but it doesn't work */
#pragma -N-
static unsigned char currentB0Contents[9]={0,0,0,0,0,0,0,0,0};
static int percussiveMode=0,currentBDContents=0;
static int opTable[18]={0,1,2,3,4,5,8,9,10,11,12,13,16,17,18,19,20,21};
static int voiceModulator[11]={0,1,2,6,7,8,12,16,14,17,13};
static int voiceCarrier[9]={3,4,5,9,10,11,15,16,17};
/* local function */
void Wait(clock_t wait);
void WriteFM(int reg, int value)
{int i;
outp(ADLIB_FM_ADDRESS, (BYTE)reg); /* set up the register */
for (i = 0; i < 6; i++) inp(ADLIB_FM_ADDRESS); /* wait 12 cycles */
outp(ADLIB_FM_DATA, (BYTE)value); /* write out the value */
for (i = 0; i < 35; i++) inp(ADLIB_FM_ADDRESS); /* wait 84 cycles */
}
int ReadFM(void)
{return (inp(ADLIB_FM_ADDRESS));
}
int AdlibExists(void)
{int stat1, stat2;
WriteFM(0x04, 0x60); /* reset both timers */
WriteFM(0x04, 0x80); /* enable timer interrupts */
stat1 = ReadFM(); /* read status register */
WriteFM(0x02, 0xFF);
WriteFM(0x04, 0x21); /* start timer 1 */
Wait(80); /* could do something useful*/
stat2 = ReadFM(); /* read status register */
WriteFM(0x04, 0x60); /* reset both timers */
WriteFM(0x04, 0x80); /* enable timer interrupts */
if (((stat1 & 0xE0) == 0x00) && ((stat2 & 0xE0) == 0xC0)) return (1);
return (0);
}
void FMReset(int percusiveMode)
{
int i;
/* zero all registers */
for (i = MIN_REGISTER; i < MAX_REGISTER+1; i++) WriteFM(i, 0);
/* allow FM chips to control the waveform of each operator */
WriteFM(0x01, 0x20);
FMSetPercusiveMode(percusiveMode);
}
void FMSetPercusiveMode(int state)
{if (state)
{WriteFM(0xBD, 0x20);
currentBDContents=0x20;
percussiveMode=1;
voiceModulator[7]=16;
voiceModulator[8]=14;
/* we have to set the freq of voice 7 & 8 for the white noise gen.*/
/* these frequency choices could certainly be better */
WriteFM(0xa7, 1844 & 0xff);
WriteFM(0xb7, 1844 >> 8);
WriteFM(0xa8, 3764 & 0xff);
WriteFM(0xb8, 3764 >> 8);
}
else
{WriteFM(0xBD, 0);
percussiveMode=0;
currentBDContents=0;
voiceModulator[7]=13;
voiceModulator[8]=14;
}
}
void FMKeyOff(int voice)
{int regNum;
/* turn voice off */
if (percussiveMode && voice>5)
{currentBDContents&=(0xFF-(16 >> (voice-6)));
WriteFM(0xBD,currentBDContents);
}
else
{regNum = 0xB0 + voice;
WriteFM(regNum, currentB0Contents[voice] & 0xdf);
/* must preserve frequency for release stage of envelope */
}
}
void FMKeyOn(int voice, int freq)
{
int regNum, tmp;
if (percussiveMode && voice>5)
{currentBDContents|=16 >> (voice-6);
if (voice==6 || voice==8) /* bass and tom-tom are pitched */
{regNum = 0xA0 + voice;
WriteFM(regNum, freq & 0xff);
regNum = 0xB0 + voice;
tmp = (freq >> 8);
WriteFM(regNum, tmp);
}
WriteFM(0xBD,currentBDContents);
}
else
{regNum = 0xA0 + voice;
WriteFM(regNum, freq & 0xff);
regNum = 0xB0 + voice;
tmp = (freq >> 8) | 0x20;
WriteFM(regNum, tmp);
currentB0Contents[voice]=tmp;
}
}
void FMVoiceVolume(int voice, int vol)
{int regNum;
regNum = 0x40+opTable[voiceModulator[voice]];
WriteFM(regNum, vol); /* must preserve KSL (but don't yet!) */
}
void FMSetVoice(int voiceNum, FMInstrument *ins)
{int modO,carO,i;
if (voiceNum<7 || !percussiveMode) /* note: base drum included */
{modO=opTable[voiceModulator[voiceNum]];
carO=opTable[voiceCarrier[voiceNum]];
WriteFM(0x20+modO,
(ins->MOD_amplitudeVibrato << 7) +
(ins->MOD_frequencyVibrato << 6) +
(ins->MOD_ss << 5) +
(ins->MOD_envelopeScaling << 4) +
(ins->MOD_fMult));
WriteFM(0x40+modO,
(ins->MOD_KSL << 6) +
(ins->MOD_outputLevel));
WriteFM(0x60+modO,
(ins->MOD_attack << 4) + (ins->MOD_decay));
WriteFM(0x80+modO,
(ins->MOD_sustain << 4) + (ins->MOD_release));
WriteFM(0xe0+modO,ins->MOD_waveForm);
WriteFM(0x20+carO,
(ins->CAR_amplitudeVibrato << 7) +
(ins->CAR_frequencyVibrato << 6) +
(ins->CAR_ss << 5) +
(ins->CAR_envelopeScaling << 4) +
(ins->CAR_fMult));
WriteFM(0x40+carO,
(ins->CAR_KSL << 6) +
(ins->CAR_outputLevel));
WriteFM(0x60+carO,
(ins->CAR_attack << 4) + (ins->CAR_decay));
WriteFM(0x80+carO,
(ins->CAR_sustain << 4) + (ins->CAR_release));
WriteFM(0xe0+carO,ins->CAR_waveForm);
if (ins->FM) /* is the adlib documentation fucked or what? */
i=0;
else
i=1;
WriteFM(0xC0+voiceNum,(ins->feedBack << 1) + i);
}
else
{modO=opTable[voiceModulator[voiceNum]];
WriteFM(0x20+modO,
(ins->MOD_amplitudeVibrato << 7) +
(ins->MOD_frequencyVibrato << 6) +
(ins->MOD_ss << 5) +
(ins->MOD_envelopeScaling << 4) +
(ins->MOD_fMult));
WriteFM(0x40+modO,
(ins->MOD_KSL << 6) +
(ins->MOD_outputLevel));
WriteFM(0x60+modO,
(ins->MOD_attack << 4) + (ins->MOD_decay));
WriteFM(0x80+modO,
(ins->MOD_sustain << 4) + (ins->MOD_release));
WriteFM(0xe0+modO,ins->MOD_waveForm);
}
}
void Wait(clock_t wait)
{clock_t goal;
if (!wait) return;
goal = wait + clock();
while ((goal > clock())) ;
}